package com.hst.capacity.domain.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.smartravel.framework.redis.DriverLocation;
import cn.smartravel.framework.redis.domain.LiveLocation;
import com.alibaba.fastjson2.JSON;
import com.hst.capacity.domain.common.constants.Constants;
import com.hst.capacity.domain.exception.BusinessException;
import com.hst.capacity.domain.model.entity.driver.DriverCertificateEntity;
import com.hst.capacity.domain.model.entity.driver.DriverEntity;
import com.hst.capacity.domain.model.entity.driver.DriverProfileEntity;
import com.hst.capacity.domain.model.entity.franchisee.commision.FranchiseeCommisionEntity;
import com.hst.capacity.domain.model.entity.vehicle.VehicleEntity;
import com.hst.capacity.domain.model.entity.vehicle.VehicleProfileEntity;
import com.hst.capacity.domain.model.entity.vehicle.VehicleTypeEntity;
import com.hst.capacity.domain.model.request.driver.DriverAddCertificateParam;
import com.hst.capacity.domain.model.request.driver.DriverAddParam;
import com.hst.capacity.domain.model.request.driver.DriverBandCarParam;
import com.hst.capacity.domain.model.request.driver.DriverSearchParam;
import com.hst.capacity.domain.model.response.OneToOnePO;
import com.hst.capacity.domain.model.response.PagingResultVO;
import com.hst.capacity.domain.model.response.agent.AgentDriverNumberCountVO;
import com.hst.capacity.domain.model.response.driver.DriverBandCarVO;
import com.hst.capacity.domain.model.response.driver.DriverInfoVO;
import com.hst.capacity.domain.service.DriverService;
import com.hst.capacity.infra.convertor.DriverConvertor;
import com.hst.capacity.infra.persistence.jpa.driver.DriverCertificateRepository;
import com.hst.capacity.infra.persistence.jpa.driver.DriverProfileRepository;
import com.hst.capacity.infra.persistence.jpa.driver.DriverRepository;
import com.hst.capacity.infra.persistence.jpa.setting.commision.FranchiseeCommisionRepository;
import com.hst.capacity.infra.persistence.jpa.vehicle.VehicleProfileRepository;
import com.hst.capacity.infra.persistence.jpa.vehicle.VehicleRepository;
import com.hst.capacity.infra.persistence.jpa.vehicle.VehicleTypeRepository;
import com.hst.capacity.infra.persistence.mybatis.DriverMapper;
import com.hst.capacity.infra.util.DateUtil;
import com.hst.capacity.infra.util.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Predicate;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Service
public class DriverServiceImpl implements DriverService {

    @Autowired
    private DriverRepository driverRepository;

    @Autowired
    private VehicleRepository vehicleRepository;

    @Autowired
    private DriverCertificateRepository certificateRepository;

    @Autowired
    private DriverMapper driverMapper;

    @Autowired
    private DriverProfileRepository driverProfileRepository;

    @Autowired
    private VehicleTypeRepository vehicleTypeRepository;

    @Autowired
    private VehicleProfileRepository vehicleProfileRepository;

    @Autowired
    private FranchiseeCommisionRepository fcRepository;

    @Autowired
    DriverLocation lastLocation;

    /**
     * 保存司机信息
     * @param param
     * @return
     */
    @Override
    public DriverEntity save(DriverAddParam param) {
        DriverEntity driverEntity = driverRepository.findByDriverMobile(param.getMobile());
        if (driverEntity != null && !driverEntity.getIdDriver().equals(param.getIdDriver()))
            throw new BusinessException(5002,"该手机号["+param.getMobile()+"]已经被使用!请检查)");

        DriverProfileEntity driverProfileEntity;
        if (driverEntity == null) {
            driverEntity = DriverConvertor.INSTANCE.convert(param);
            driverProfileEntity = newDriverProfileEntity(param);
            driverEntity.setIdDriver(StringUtil.generateUuid());
            String idDriverProfile = StringUtil.generateUuid();
            driverProfileEntity.setIdDriverProfile(idDriverProfile);
            driverEntity.setIdDriverProfile(idDriverProfile);
            driverEntity.setCreateOrderRole(Constants.CreateOrderRole.NO_CREATE_ROLE);
            driverEntity.setFaceVerify(0);
        } else {
            String idDriverProfile = driverEntity.getIdDriverProfile();
            DriverConvertor.INSTANCE.convert(driverEntity, param);
            if (StringUtil.isNotBlank(idDriverProfile)) {
                driverProfileEntity = driverProfileRepository.findByIdDriverProfile(idDriverProfile);
            } else {
                idDriverProfile = StringUtil.generateUuid();
            }
            driverProfileEntity = newDriverProfileEntity(param);
            driverProfileEntity.setIdDriverProfile(idDriverProfile);
            driverEntity.setIdDriverProfile(idDriverProfile);
        }

//        if (StrUtil.isNotEmpty(param.getIdDriver())){
//            if ((driverEntity=driverRepository.findByIdDriver(param.getIdDriver()))==null)
//                throw new BusinessException(5002,"编辑的司机ID不存在,请检查");
//            DriverConvertor.INSTANCE.convert(driverEntity, param);
//            if (StrUtil.isEmpty(driverEntity.getIdDriverProfile()))
//                throw new BusinessException(5002,"司机表[idDriverProfile]数据不能为空,请检查");
//            driverProfileEntity = driverProfileRepository.findByIdDriverProfile(driverEntity.getIdDriverProfile());
//            DriverConvertor.INSTANCE.convert(driverProfileEntity, param);
//        }else {
//            driverEntity = newDriverEntity(param);
//            driverProfileEntity = newDriverProfileEntity(param);
//            driverEntity.setIdDriver(StringUtil.generateUuid());
//            String s = StringUtil.generateUuid();
//            driverProfileEntity.setIdDriverProfile(s);
//            driverEntity.setIdDriverProfile(s);
//        }

        driverProfileRepository.save(driverProfileEntity);
        return driverRepository.save(driverEntity);
    }

    @Override
    public String deviceUnband(String idDriver) {
        DriverEntity d = driverRepository.findByIdDriver(idDriver);
        if (d == null)
            throw new BusinessException(5001,"未找到该司机信息");

        d.setBindDeviceSn(null);
        return driverRepository.save(d).getIdDriver();
    }

    @Override
    public DriverInfoVO driverInfo(String idDriver) {
        DriverEntity d = driverRepository.findByIdDriver(idDriver);
        if (d == null)
            return null;

        DriverInfoVO vo = DriverConvertor.INSTANCE.convert2Info(d);
        if (StringUtil.isNotBlank(d.getIdDriverProfile())) {
            DriverProfileEntity dp = driverProfileRepository.findByIdDriverProfile(d.getIdDriverProfile());
            if (dp != null) {
                vo.setRealName(dp.getRealName());
                vo.setNickName(dp.getNickName());
                vo.setGender(dp.getGender());
                vo.setJobType(dp.getJobType());
                vo.setQrcode(dp.getQrcode());
            }
        }

        VehicleEntity v = vehicleRepository.findByIdVehicle(d.getIdVehicle());
        if (v != null) {
            vo.setIdVehicle(v.getIdVehicle());
            vo.setIdVehicleType(v.getIdVehicleType());
            vo.setVehicleName(v.getVehicleName());
            vo.setPlateNumber(v.getPlateNumber());

            VehicleTypeEntity vt = vehicleTypeRepository.findByIdVehicleType(v.getIdVehicleType());
            if (vt != null) {
                //vo.setColor(v.getColor());
                vo.setVehicleTypeName(vt.getShortName());
                vo.setSeating(vt.getSeats());
            }
        }

        VehicleProfileEntity vp = vehicleProfileRepository.findByIdVehicle(d.getIdVehicle());
        if (vp != null) {
            vo.setColor(vp.getColor());
            vo.setModel(vp.getModel());
            vo.setBrand(vp.getBrand());
        }

        return vo;
    }

    /**
     * 司机绑定车辆
     * @param param
     * @return
     */
    @Override
    public DriverBandCarVO driverBandVehicle(DriverBandCarParam param) {
        if (driverRepository.findByIdDriver(param.getIdDriver())==null)
            throw new BusinessException(5002,"绑定的司机不存在，请检查");

        VehicleEntity v = vehicleRepository.findByPlateNumber(param.getPlateNumber());
        if (v==null)
            throw new BusinessException(5002,"该车牌的车辆不存在，请检查");

        DriverEntity byVehicleEntity = driverRepository.findByIdVehicle(v.getIdVehicle());
//        if (byVehicleEntity !=null)
//            throw new BusinessException(4003,"该车牌的车辆已被他人绑定");可以被多人绑定

        driverRepository.driverBandVehicle(v.getIdVehicle(),param.getIdDriver());
        return findDriverEntityByIdDriver(param.getIdDriver());
    }

    @Override
    public LiveLocation driverLocation(String idDriver) {
        return lastLocation.getLiveLocation(idDriver);
    }

    /**
     * 分页并条件查询司机信息
     * @param param
     * @return
     */
    @Override
    public PagingResultVO<DriverEntity> searchWithConditionsAndPaging(DriverSearchParam param) {

        Page<DriverEntity> page = driverRepository.findAll((root, query, criteriaBuilder) -> {
            // 定义条件LIST
            List<Predicate> predicates = new ArrayList<>();
            // 按行政代码in查找
            if (StrUtil.isNotEmpty(param.getCityCode())) {
                List<String> strings = Convert.toList(String.class, param.getCityCode());
                CriteriaBuilder.In<String> in = criteriaBuilder.in(root.get("regionCode"));
                for (String v:strings) {
                    in.value(v);
                }
                predicates.add(criteriaBuilder.and(in));
            }
            //按账号状态in查找
            if (ObjectUtil.isNotEmpty(param.getStatus())) {
                List<Integer> strings = Convert.toList(Integer.class, param.getStatus());
                CriteriaBuilder.In<Integer> in = criteriaBuilder.in(root.get("status"));
                for (Integer v:strings) {
                    in.value(v);
                }
                predicates.add(criteriaBuilder.and(in));
            }
            //按工作类型in查找
            if (ObjectUtil.isNotEmpty(param.getDriveType())) {
                List<Integer> strings = Convert.toList(Integer.class, param.getDriveType());
                CriteriaBuilder.In<Integer> in = criteriaBuilder.in(root.get("driverProfile").get("jobType"));
                for (Integer v:strings) {
                    in.value(v);
                }
                predicates.add(criteriaBuilder.and(in));
            }
            //按司机driverCode用户名精确查找
//            if (ObjectUtil.isNotEmpty(param.getIdDriver())) {
//                predicates.add(criteriaBuilder.equal(root.get("driverCode"),param.getIdDriver()));
//            }
            //按司机手机号精确查找
            if (ObjectUtil.isNotEmpty(param.getPhoneDriver())) {
                predicates.add(criteriaBuilder.equal(root.get("driverMobile"),param.getPhoneDriver()));
            }
            //按代理商in查找
            if (ObjectUtil.isNotEmpty(param.getIdAgent())) {
                List<String> strings = Convert.toList(String.class, param.getIdAgent());
                CriteriaBuilder.In<String> in = criteriaBuilder.in(root.get("idAgent"));
                for (String v:strings) {
                    in.value(v);
                }
                predicates.add(criteriaBuilder.and(in));
            }
            //按代理商in查找
            if (ObjectUtil.isNotEmpty(param.getIdFranchisee())) {
                List<String> strings = Convert.toList(String.class, param.getIdFranchisee());
                CriteriaBuilder.In<String> in = criteriaBuilder.in(root.get("idFranchisee"));
                for (String v:strings) {
                    in.value(v);
                }
                predicates.add(criteriaBuilder.and(in));
            }
            //按姓名模糊查找
            if (ObjectUtil.isNotEmpty(param.getRealName())) {
                predicates.add(criteriaBuilder.and(criteriaBuilder.like(root.get("driverProfile").get("realName"),param.getRealName())));
            }

            //排序
            query.orderBy(criteriaBuilder.desc(root.get("createTime")));

            Predicate[] array = predicates.toArray(new Predicate[0]);
            return criteriaBuilder.and(array);
        }, PageRequest.of(param.getPageIndex() - 1, param.getPageSize()));

        return new PagingResultVO<>(page.getTotalElements(), page.getContent());
    }

    /**
     * 查询司机绑定车辆信息
     * @param idDriver
     * @return
     */
    @Override
    public DriverBandCarVO findDriverEntityByIdDriver(String idDriver) {
        return driverMapper.findDriverEntityByIdDriver(idDriver);
    }

    @Override
    public Object driverAddCertificate(DriverAddCertificateParam param) {
        DriverCertificateEntity driverCertificateEntity = newDriverCertificateEntity(param);
        DriverCertificateEntity save = certificateRepository.save(driverCertificateEntity);
//        List<DriverCertificateEntity> all = certificateRepository.findAll();
        return save;
    }

    @Override
    public DriverAddCertificateParam driverAddCertificateSelect(String idDriver) {
        DriverCertificateEntity find = certificateRepository.findByIdDriver(idDriver);
        DriverAddCertificateParam re = DriverConvertor.INSTANCE.convert(find);
        if (find==null)return null;
        if (find.getCertificatea()==null){
            re.setIsCruise(1);
            re.setCertificatea(find.getCertificateb());
        }
        else re.setIsCruise(0);
        return re;
    }

    @Override
    public AgentDriverNumberCountVO driverAgentCount(String idAgent) {
        AgentDriverNumberCountVO returns = new AgentDriverNumberCountVO();
        List<OneToOnePO<DriverEntity, DriverProfileEntity>> oneToOnePOS = driverRepository.queryByIdAgent(idAgent);
        returns.setDriverNumber(oneToOnePOS.size());
        int driverMouthNumber = 0;
        int driverOnlineNumber = 0;
        int driverUnOnlineNumber = 0;
        int driverJobType0Number = 0;
        int driverJobType1Number = 0;
        for (OneToOnePO<DriverEntity, DriverProfileEntity> oneToOnePO:oneToOnePOS) {
            Duration between = LocalDateTimeUtil.between(oneToOnePO.getF().getCreateTime(), LocalDateTimeUtil.now());
            long l = between.toDays();
            if (between.toDays()<=30)
                driverMouthNumber++;
            if (oneToOnePO.getF().getOperationStatus()==0)driverUnOnlineNumber++;
            else driverOnlineNumber++;
            try {
                if (oneToOnePO.getS().getJobType()==0)driverJobType0Number++;
                else driverJobType1Number++;
            }catch (NullPointerException exception){
                //job类型为空
            }

        }
        returns.setDriverMouthNumber(driverMouthNumber);
        returns.setDriverUnOnlineNumber(driverUnOnlineNumber);
        returns.setDriverOnlineNumber(driverOnlineNumber);
        returns.setDriverJobType0Number(driverJobType0Number);
        returns.setDriverJobType1Number(driverJobType1Number);
        return returns;
    }

    @Override
    public DriverEntity findDriverByIdFranchiseeWithRand(String idFranchisee) {
        return driverRepository.findDriverByIdFranchiseeWithRand(idFranchisee);
    }

    private DriverCertificateEntity newDriverCertificateEntity(DriverAddCertificateParam param) {
        DriverCertificateEntity driverCertificateEntity = new DriverCertificateEntity();
        String idCertificate;//表映射关系有问题，暂时这样处理
        try {
            idCertificate = certificateRepository.findByIdDriver(param.getIdDriver()).getIdDriverNetworkCertificate();
            if (StrUtil.isNotEmpty(idCertificate))
                driverCertificateEntity.setIdDriverNetworkCertificate(idCertificate);
        }catch (Exception e){

        }
        if (param.getIsCruise()==0){
            driverCertificateEntity.setCertificatea(param.getCertificatea());
            driverCertificateEntity.setCertificateb(null);
        }else {
            driverCertificateEntity.setCertificatea(null);
            driverCertificateEntity.setCertificateb(param.getCertificatea());
        }
        driverCertificateEntity.setNetworkCarissueOrganization(param.getNetworkCarissueOrganization());
        driverCertificateEntity.setNetworkCarissueDate(DateUtil.parseLocalDateTime(param.getNetworkCarissueDate()));
        driverCertificateEntity.setNetworkCarproofDate(DateUtil.parseLocalDateTime(param.getNetworkCarproofDate()));
        driverCertificateEntity.setNetworkCarproofOn(DateUtil.parseLocalDateTime(param.getNetworkCarproofOn()));
        driverCertificateEntity.setNetworkCarproofOff(DateUtil.parseLocalDateTime(param.getNetworkCarproofOff()));
        driverCertificateEntity.setCommercialType(param.getCommercialType());
        driverCertificateEntity.setContractCompany("");
        driverCertificateEntity.setContractStartTime(null);
        driverCertificateEntity.setContractEndTime(null);
        driverCertificateEntity.setIdDriver(param.getIdDriver());
//        driverCertificateEntity.setDriverEntity(new DriverEntity(param.getIdDriver()));
//        driverCertificateEntity.setCreateBy();
//        driverCertificateEntity.setCreateTime();
//        driverCertificateEntity.setUpdateBy();
//        driverCertificateEntity.setUpdateTime();
        return driverCertificateEntity;

    }
    private DriverEntity newDriverEntity(DriverAddParam param){
        DriverEntity driverEntity = new DriverEntity();
//        driverEntity.setIdDriver();
        driverEntity.setIdFranchisee(param.getIdFranchisee());
        driverEntity.setDriverCode(param.getDriverCode());
        driverEntity.setIdVehicle("");
//        driverEntity.setIdDriverProfile("");
        driverEntity.setDriverIntercityNum("");
        driverEntity.setDriverMobile(param.getMobile());
        driverEntity.setPassword(Constants.DEFAULT_DRIVER_PASSWORD);
        driverEntity.setRegionCode(param.getRegionCode());
        driverEntity.setIcon(param.getIcon());
        driverEntity.setBindDeviceSn("");
        driverEntity.setIntroducer("");
        driverEntity.setCreateOrderRole(0);
        driverEntity.setIsAgreement(1);
        driverEntity.setRemark("");
        driverEntity.setStatus(Constants.DriverStatus.OFFLINE);
        driverEntity.setOperationStatus(Constants.DriverOperationStatus.OFFLINE);
        driverEntity.setGpsPn("");
        driverEntity.setRegisterDate(LocalDateTimeUtil.now());
        driverEntity.setRegisterFrom("后台");
        driverEntity.setLoginFailureTimes(0);
        driverEntity.setLastLoginTime(null);
        driverEntity.setTranFlag(Constants.DEFAULTSTATUS);
        driverEntity.setIdAgent(param.getIdAgent());
        driverEntity.setIdCertificate("");
//        driverEntity.setCreateBy();
//        driverEntity.setCreateTime();
//        driverEntity.setUpdateBy();
//        driverEntity.setUpdateTime();
        return driverEntity;
    }
    private DriverProfileEntity newDriverProfileEntity(DriverAddParam param){
        DriverProfileEntity driverProfileEntity = new DriverProfileEntity();
//        driverProfileEntity.setIdDriverProfile();
        driverProfileEntity.setRealName(param.getFullName());
        driverProfileEntity.setBirthday(null);
        driverProfileEntity.setIdCardNo(param.getIdCard());
        driverProfileEntity.setIdCardFront(param.getIdCardFront());
        driverProfileEntity.setIdCardVerso(param.getIdCardVerso());
        driverProfileEntity.setNickName(null);
        driverProfileEntity.setGender(param.getGender());
        driverProfileEntity.setLicenseTime(null);
        driverProfileEntity.setJobTime(null);
        driverProfileEntity.setJobType(param.getJobType());//0 自营司机 1 加盟司机
        driverProfileEntity.setServiceScope(param.getServiceScope());
        driverProfileEntity.setIdGrade(null);
        driverProfileEntity.setServiceTimes(null);
        driverProfileEntity.setLicenseType(param.getLicenseType());
        driverProfileEntity.setHeight(null);
        driverProfileEntity.setOrigin(null);
        driverProfileEntity.setFamilyAddress(param.getAddress());
        driverProfileEntity.setEmergencyContact(null);
        driverProfileEntity.setEmergencyPhone(null);
        driverProfileEntity.setEmergencyContactAddress(null);
        driverProfileEntity.setDrivingLicenseNo(param.getDrivingLicenseNo());
        driverProfileEntity.setDrivingLicense(param.getDrivingLicense());
        driverProfileEntity.setDrivingLicenseSub(param.getDrivingLicenseSub());
        LocalDateTime licenseTime = null;
        if (StringUtil.isNotBlank(param.getLicenseTime())) {
            licenseTime = DateUtil.parseLocalDateTime(param.getLicenseTime());
        }
        driverProfileEntity.setLicenseTime(licenseTime);
        driverProfileEntity.setLicenseStart(DateUtil.parseLocalDateTime(param.getLicenseStart()));
        driverProfileEntity.setLicenseEnd(DateUtil.parseLocalDateTime(param.getLicenseEnd()));
//        driverProfileEntity.setVehcileLicenseNo(null);
        driverProfileEntity.setNationality(null);
        driverProfileEntity.setNation(null);
        driverProfileEntity.setMaritalstatus(null);
        driverProfileEntity.setLanguagelevel(null);
        driverProfileEntity.setEducation(null);
        driverProfileEntity.setCensus(null);
        driverProfileEntity.setCensusAddress(null);
        driverProfileEntity.setTaxiCertificate(null);
        driverProfileEntity.setDriverPhoto(param.getDriverPhoto());
        driverProfileEntity.setMemo(null);
        driverProfileEntity.setQrcode(param.getQrcode());
//        driverProfileEntity.setCreateBy();
//        driverProfileEntity.setCreateTime();
//        driverProfileEntity.setUpdateBy();
//        driverProfileEntity.setUpdateTime();
        return driverProfileEntity;
    }

    @Override
    public float driverRate(String idFranchisee,int moduleType) {
        float driverRate = 0.75f;

        FranchiseeCommisionEntity franchiseeCommisionEntity = null;
        if (StringUtil.isNotBlank(idFranchisee))
            franchiseeCommisionEntity = fcRepository.findByChannelAndIdFranchiseeAndModuleType(Constants.Channel.TONGCHENG_RIDE, idFranchisee,moduleType);
        if (franchiseeCommisionEntity != null) {
            driverRate =  franchiseeCommisionEntity.getDriverRate()/100;
        }

        return driverRate;
    }

}
